﻿using System;


namespace BizElements.BusinessLayer
{
    /// <summary>
    /// Provides methods which classify the basic .NET types.
    /// </summary>
    public static class TypeUtil
    {
        #region IsInteger.

        /// <summary>
        /// Indicates whether the given type is an integer number (Int32, Byte, Long etc.).
        /// </summary>
        /// <param name="t">Type to be tested.</param>
        /// <returns>True if a given type is an integral type; false otherwise.</returns>
        public static bool IsInteger(Type t)
        {
            if (t == typeof(Int32) || t == typeof(Byte) || t == typeof(Int16) || t == typeof(Int64) || t == typeof(SByte) || t == typeof(UInt16) || t == typeof(UInt32) || t == typeof(Int64))
                return true;
            else
                return false;
        }

        #endregion

        #region IsFloatingPointNumber.

        /// <summary>
        /// Indicates wheter the given type is a floating point number (Single, Double, Decimal).
        /// </summary>
        /// <param name="t">Type to be tested.</param>
        /// <returns>True if a given type is an integral type; false otherwise.</returns>
        public static bool IsFloatingPointNumber(Type t)
        {
            if (t == typeof(Single) || t == typeof(Double) || t == typeof(Decimal))
                return true;
            else
                return false;
        }

        #endregion

        #region IsNumber.

        /// <summary>
        /// Indicates whether the given type is a number (integer or real number).
        /// </summary>
        /// <param name="t">Type to be tested.</param>
        /// <returns>True if a given type is an integral type; false otherwise.</returns>
        public static bool IsNumber(Type t)
        {
            if (IsFloatingPointNumber(t) || IsInteger(t))
                return true;
            else
                return false;
        }

        #endregion

        #region IsDate.

        /// <summary>
        /// Indicates whether the given type is a date type.
        /// </summary>	
        /// <param name="t">Type to be tested.</param>
        /// <returns>True if a given type is an integral type; false otherwise.</returns>
        public static bool IsDate(Type t)
        {
            if (t == typeof(DateTime))
                return true;
            else
                return false;
        }

        #endregion

        #region IsText.

        /// <summary>
        /// Indicates whether the given type is textual (String, Char, Char[]).
        /// </summary>
        /// <param name="t">Type to be tested.</param>
        /// <returns>True if a given type is an integral type; false otherwise.</returns>
        public static bool IsText(Type t)
        {
            if (t == typeof(String) || t == typeof(Char) || t == typeof(Char[]))
                return true;
            else
                return false;
        }

        #endregion

        #region IsBoolean.

        /// <summary>
        /// Indicates whether the given type is an boolean type (bool).
        /// </summary>
        /// <param name="t">Type to be tested.</param>
        /// <returns>True if a given type is a boolean type; false otherwise.</returns>
        public static bool IsBoolean(Type t)
        {
            return (t == typeof(bool));
        }

        #endregion

        #region IsGuid.

        /// <summary>Indicates whether the given type is GUID.</summary>
        /// <param name="t">Type to be tested.</param>
        /// <returns>True if a given type is a GUID type; false otherwise.</returns>
        public static bool IsGuid(Type t)
        {
            return (t == typeof(Guid));
        }

        #endregion

        /// <summary>Casts object to nullable value type.</summary>
        /// <typeparam name="T">Value type.</typeparam>
        /// <param name="val">Boxed value of the specified type or null.</param>
        /// <returns>Casted vaue or null.</returns>
        public static T? CastTo<T>(object val)
            where T : struct
        {
            if (IsNull(val))
                return null;
            else
                return (T)val;
        }

        /// <summary>Checks if the provided value is a <b>null</b> reference or <see cref="System.DBNull.Value"/>.</summary>
        /// <param name="val">An object.</param>
        /// <returns><b>true</b> if the provided value is a <b>null</b> reference or <see cref="System.DBNull.Value"/>; otherwise <b>false</b></returns>
        public static bool IsNull(object val)
        {
            return (val == DBNull.Value || val == null);
        }

        /// <summary>Replaces <see cref="System.DBNull.Value"/> with <b>null</b> reference.</summary>
        /// <param name="dbValue">Database value.</param>
        /// <returns>If provided value is <see cref="System.DBNull.Value"/> then <b>null</b> is returned; otherwise the original value is returned.</returns>
        public static object ReplaceDbNull(object dbValue)
        {
            return (dbValue != DBNull.Value) ? dbValue : null;
        }
    }
}